package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huiminpay.common.cache.Cache;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.RedisUtil;
import com.huiminpay.transaction.api.PayChannelService;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;
import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 有点儿意思
 * @Description:
 */
@Service
public class PayChannelServiceImpl  implements PayChannelService {

    @Autowired
    PlatformChannelMapper platformChannelMapper;

    @Autowired
    AppPlatformChannelMapper appPlatformChannelMapper;

    @Autowired
    PayChannelParamMapper payChannelParamMapper;

    @Autowired
    Cache cache;


    /**
     * 获取服务类型列表
     *
     * @return 服务类型列表
     * @throws BusinessException
     */
    @Override
    public List<PlatformChannelDTO> queryPlatformChannel() throws BusinessException {
        List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);
        return PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);
    }

    /**
     * 应用绑定服务类型
     *
     * @param appId           应用id
     * @param platChannelCode 服务类型编码
     */
    @Override
    public void insertAppPlatformChannel(String appId, String platChannelCode) {
        //先查询是否绑定过
        AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, platChannelCode));
        if (appPlatformChannel == null) {
            //说明没有绑定
            appPlatformChannel = new AppPlatformChannel();
            appPlatformChannel.setAppId(appId);
            appPlatformChannel.setPlatformChannel(platChannelCode);
            appPlatformChannelMapper.insert(appPlatformChannel);
        }
    }

    /**
     * 查询应用是否绑定了某个服务类型
     *
     * @param appId           应用id
     * @param platChannelCode 服务类型编码
     * @return 1 已绑定 否则返回 0
     */
    @Override
    public Integer queryAppPlatformChannel(String appId, String platChannelCode) {

        Integer count = appPlatformChannelMapper.selectCount(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, platChannelCode));
        if (count > 0) {
            // 已绑定
            return 1;
        }
        return 0;
    }

    /**
     * 根据支付渠道编码查询原始支付渠道
     * @param platformChannelCode 支付渠道编码
     * @return List原始支付渠道
     */
    @Override
    public List<PayChannelDTO> queryPayChannel(String platformChannelCode) {
        return platformChannelMapper.selectPayChannelByPlatformChannel(platformChannelCode);
    }

    /**
     * 保存支付渠道 参数
     * @param payChannelParamDTO 支付渠道封装对象
     * @throws BusinessException
     */
    @Override
    public void insertPayChannel(PayChannelParamDTO payChannelParamDTO) throws BusinessException {
        //1.参数判空
        if (payChannelParamDTO == null
                || payChannelParamDTO.getAppId() == null
                || payChannelParamDTO.getPayChannel() ==null
                || payChannelParamDTO.getPlatformChannelCode() == null){
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        //2.判断应用是否与服务类型绑定
        //查询到应用与服务类型绑定id
        Long channelParamId = this.queryPayChannelParamId(payChannelParamDTO.getAppId(), payChannelParamDTO.getPlatformChannelCode());
        if (channelParamId == null){
            throw new BusinessException(CommonErrorCode.E_300010);
        }
        //3.判断是否设置过支付参数
        PayChannelParam payChannelParam = payChannelParamMapper.selectOne(new LambdaQueryWrapper<PayChannelParam>()
                .eq(PayChannelParam::getAppPlatformChannelId, channelParamId)
                .eq(PayChannelParam::getPayChannel, payChannelParamDTO.getPayChannel()));
        if (payChannelParam != null){
            //说明配置过参数  直接修改
            payChannelParam.setParam(payChannelParamDTO.getParam());
            payChannelParam.setChannelName(payChannelParamDTO.getChannelName());
            payChannelParamMapper.updateById(payChannelParam);
        }else{
            //说明不存在  插入配置参数
            //4.设置必要参数
            payChannelParam = PayChannelParamConvert.INSTANCE.dto2entity(payChannelParamDTO);
            payChannelParam.setAppPlatformChannelId(channelParamId);
            payChannelParamMapper.insert(payChannelParam);
        }
        //更新缓存
        this.updateCache(payChannelParamDTO.getAppId(), payChannelParamDTO.getPayChannel());
    }

    /**
     * 更新缓存方法
     * @param appId 应用id
     * @param platformChannel 服务类型编码
     */
    private void updateCache(String appId ,String platformChannel){
        //1.构造key
        String key = RedisUtil.keyBuilder(appId, platformChannel);
        //2.查缓存
        //2.1有则删除
        if (cache.exists(key)){
            cache.del(key);
        }
        //更新
        List<PayChannelParamDTO> channelParamDtoS = this.queryPayChannelParams(appId, platformChannel);
        if (channelParamDtoS != null){
            String jsonString = JSONObject.toJSONString(channelParamDtoS);
            cache.set(key,jsonString);
        }
    }

    /**
     * 获取支付渠道参数列表
     * @param appId           应用id
     * @param platformChannel 服务类型编码
     * @return 支付渠道参数列表
     */
    @Override
    public List<PayChannelParamDTO> queryPayChannelParams(String appId, String platformChannel) {
        //构造key
        String key = RedisUtil.keyBuilder(appId, platformChannel);
        String jsonStr = cache.get(key);
        if (!StringUtils.isEmpty(jsonStr)) {
            // 如果有直接返回
            return JSONObject.parseArray(jsonStr, PayChannelParamDTO.class);
        }
        //没有 去查数据库
        //查询应用与服务类型绑定id
        Long paramId = this.queryPayChannelParamId(appId, platformChannel);
        if (paramId != null){
            List<PayChannelParam> payChannelParams = payChannelParamMapper.selectList(new LambdaQueryWrapper<PayChannelParam>().eq(PayChannelParam::getAppPlatformChannelId, paramId));
           if (payChannelParams != null){
               //把数据转成json
               List<PayChannelParamDTO> channelParamDtoS = PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParams);
               String jsonString = JSONObject.toJSONString(channelParamDtoS);
               //查到的数据再放入缓存中
               cache.set(key,jsonString);
               return channelParamDtoS;
           }
        }
        return null;
    }

    /**
     * 获取某个应用下的支付渠道参数
     * @param appId           应用id
     * @param platformChannel 服务类型编码
     * @param payChannel      支付渠道
     * @return 支付渠道参数
     */
    @Override
    public PayChannelParamDTO queryPayChannelParamByAppPlatformChannel(String appId, String platformChannel, String payChannel) {
        List<PayChannelParamDTO> channelParamDtoS = this.queryPayChannelParams(appId, platformChannel);
        for (PayChannelParamDTO channelParamDto : channelParamDtoS) {
            if (payChannel.equals(channelParamDto.getPayChannel())) {
                return channelParamDto;
            }
        }
        return null;
    }

    /**
     * 查询应用与服务类型的绑定id
     * @param appId 应用id
     * @param platChannelCode 服务类型编码
     * @return 应用与服务类型绑绑定id
     */
    private Long queryPayChannelParamId(String appId,String platChannelCode){
        AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, platChannelCode));
        if (appPlatformChannel != null) {
            return appPlatformChannel.getId();
        }
        return null;
    }
}